package com.shop.cloud.controller.pay;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.TreeMap;

import org.json.JSONObject;
import org.json.XML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.shop.cloud.SpringUtils;
import com.shop.cloud.config.ConfigUtil;
import com.shop.cloud.domain.hongfu.IosWxParams;
import com.shop.cloud.domain.hongfu.WeixinConfig;
import com.shop.cloud.service.hongfu.IWeixinConfigService;


/**
 * 微信支付后台配置
 * @author Yan Weiwei
 *
 */
@Component
public class WeixinPayConfig {
	
	private Logger logger = LoggerFactory.getLogger(WeixinPayConfig.class);
	
	@Autowired
	private IWeixinConfigService weixinConfigService;
	
	private static final String API_CREATE_PREPAY = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	
	/**
	 * 封装成xml格式
	 * @param postData
	 * @param appKey
	 * @return
	 * @throws Exception
	 */
	public String getDataStr4Map(TreeMap<String, String> postData, String appKey) throws Exception{
		String tmp = "<xml>";
		List<String> params = new ArrayList<String>();
		
		for(Iterator<String> it = postData.keySet().iterator(); it.hasNext(); ){ 
			String key = it.next();
			String value = postData.get(key);
			params.add(key + "=" +value);
			tmp += "<"+key+">" + value + "</"+key+">";
		}
		
		String sign = implode("&", params);
		
		tmp = tmp + "<sign>" + Sign(sign, appKey) + "</sign>";
		tmp = tmp.concat("</xml>");
		
		logger.info("************pay xml info**************"+tmp);
		
		return tmp;
	}

	/**
	 * 生成微信预订单-余额
	 * @param no
	 * @param ip
	 * @param orderFee
	 * @return
	 * @throws Exception
	 */
	public String createPrepayOrder(String no, String ip, String orderFee) throws Exception {
		//初始化预订单ID
		String prepay_id = "";
		//单位为分
		String total_fee = Math.round(Double.parseDouble(orderFee) * 100) + "";
		//获取微信配置信息
		WeixinConfig weixinConfig = weixinConfigService.get(new Long(1));
		
		TreeMap<String, String> postData = new TreeMap<String, String>();
		postData.put("appid", weixinConfig.getAppid());
		postData.put("mch_id", weixinConfig.getMchid());
		postData.put("nonce_str", getRandomString(32));
		postData.put("body", "充值余额");
		postData.put("out_trade_no", no);
		postData.put("total_fee", total_fee.toString());
		postData.put("spbill_create_ip", ip);
//		String url = SpringUtils.getBean(ConfigUtil.class).getWeixinCallbackUrl();
//		postData.put("notify_url", url+"api/weixinCallback");
		postData.put("notify_url", PayController.Weixin_Call_Back_Url+"api/weixinCallback");
		postData.put("trade_type", "APP");
		System.err.println(" url  "+PayController.Weixin_Call_Back_Url+"api/weixinCallback");
		String postDataStr = getDataStr4Map(postData, weixinConfig.getAppkey());
		
		logger.info("************create prepay postData**************"+postDataStr);
		
		String msg = postXMLURL(API_CREATE_PREPAY, postDataStr);
		
		JSONObject resultDatas = XML.toJSONObject(msg);
		
		JSONObject resultData = resultDatas.getJSONObject("xml");
		
		logger.info("************prepay return msg**************"+resultData);
		
		if(resultData.getString("return_code").equals("SUCCESS")){
        	if(resultData.getString("result_code").equals("SUCCESS")){
        		prepay_id = resultData.getString("prepay_id");
        	}else{
        		logger.info("************err_code_des************"+resultData.getString("err_code_des"));
            }
        }else{
        	logger.info("************return_msg************"+resultData.getString("return_msg"));
        }
		
		return prepay_id;
	}
	
	/**
	 * 生成微信预订单-积分
	 * @param no
	 * @param ip
	 * @param orderFee
	 * @return
	 * @throws Exception
	 */
	public String createPrepayOrderForPonits(String no, String ip, String orderFee) throws Exception {
		//初始化预订单ID
		String prepay_id = "";
		//单位为分
		String total_fee = Math.round(Double.parseDouble(orderFee) * 100) + "";
		//获取微信配置信息
		WeixinConfig weixinConfig = weixinConfigService.get(new Long(1));
		
		TreeMap<String, String> postData = new TreeMap<String, String>();
		postData.put("appid", weixinConfig.getAppid());
		postData.put("mch_id", weixinConfig.getMchid());
		postData.put("nonce_str", getRandomString(32));
		postData.put("body", "充值积分");
		postData.put("out_trade_no", no);
		postData.put("total_fee", total_fee.toString());
		postData.put("spbill_create_ip", ip);
//		String url = SpringUtils.getBean(ConfigUtil.class).getWeixinCallbackUrl();
//		postData.put("notify_url", url+"api/weixinCallback");
		postData.put("notify_url",  PayController.Weixin_Call_Back_Url+"api/weixinCallbackForPoints");
		System.err.println(" url  "+PayController.Weixin_Call_Back_Url+"api/weixinCallbackForPoints");
		postData.put("trade_type", "APP");
		
		String postDataStr = getDataStr4Map(postData, weixinConfig.getAppkey());
		
		logger.info("************create prepay postData**************"+postDataStr);
		
		String msg = postXMLURL(API_CREATE_PREPAY, postDataStr);
		
		JSONObject resultDatas = XML.toJSONObject(msg);
		
		JSONObject resultData = resultDatas.getJSONObject("xml");
		
		logger.info("************prepay return msg**************"+resultData);
		
		if(resultData.getString("return_code").equals("SUCCESS")){
        	if(resultData.getString("result_code").equals("SUCCESS")){
        		prepay_id = resultData.getString("prepay_id");
        	}else{
        		logger.info("************err_code_des************"+resultData.getString("err_code_des"));
            }
        }else{
        	logger.info("************return_msg************"+resultData.getString("return_msg"));
        }
		
		return prepay_id;
	}
	
	/**
	 * 帮ios处理支付请求参数
	 * @param prepay_id
	 * @return
	 * @throws Exception
	 */
	public IosWxParams handleIosWxParams(String prepay_id) throws Exception{
		IosWxParams iosWxParams = new IosWxParams();
		//获取微信配置信息
		WeixinConfig weixinConfig = weixinConfigService.get(new Long(1));
		
		TreeMap<String, String> postData = new TreeMap<String, String>();
		postData.put("appid", weixinConfig.getAppid());
		iosWxParams.setAppid(weixinConfig.getAppid());
		postData.put("partnerid", weixinConfig.getMchid());
		iosWxParams.setPartnerid(weixinConfig.getMchid());
		postData.put("prepayid", prepay_id);
		iosWxParams.setPrepayid(prepay_id);
		postData.put("package", "Sign=WXPay");
		iosWxParams.setPackages("Sign=WXPay");
		String noncestr = getRandomString(32);
		postData.put("noncestr", noncestr);
		iosWxParams.setNoncestr(noncestr);
		String timestamp = String.valueOf(new Date().getTime()/1000);
		postData.put("timestamp", Integer.valueOf(timestamp)+"");
		iosWxParams.setTimestamp(Integer.valueOf(timestamp)+"");
		
		List<String> params = new ArrayList<String>();
		for(Iterator<String> it = postData.keySet().iterator(); it.hasNext(); ){ 
			String key = it.next();
			String value = postData.get(key);
			params.add(key + "=" +value);
		}
		
		String sign = implode("&", params);
		iosWxParams.setSign(Sign(sign, weixinConfig.getAppkey()));
		
		return iosWxParams;
	}
	
	/**
	 * 生成随机字符串
	 * @param length 字符串长度
	 * @return
	 */
	public static String getRandomString(int length) { 
	    String base = "abcdefghijklmnopqrstuvwxyz0123456789";     
	    Random random = new Random();     
	    StringBuffer sb = new StringBuffer();     
	    for (int i = 0; i < length; i++) {     
	        int number = random.nextInt(base.length());     
	        sb.append(base.charAt(number));     
	    }     
	    return sb.toString();     
	 }
    
    /**
     * MD5加密
     * @param s
     * @return
     */
    public final static String MD5(String s) {
        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};       
        try {
            byte[] btInput = s.getBytes("utf-8");
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
       }
	}
    
    /**
	 * http service post 请求
	 * 返回解析xml str
	 * @param request
	 * @param urlStr
	 * @param postData
	 * @return
	 * @throws IOException 
	 */
	public static String postXMLURL(String urlStr, String postData){
		String result = null;
		try {
            URL url = new URL(urlStr);// 创建连接  
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
            connection.setDoOutput(true);  
            connection.setDoInput(true);  
            connection.setUseCaches(false);  
            connection.setInstanceFollowRedirects(true);  
            connection.setRequestMethod("POST"); // 设置请求方式  
            connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式  
            connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式  
            connection.connect();  
            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); // utf-8编码  
            out.append(postData);  
            out.flush();  
            out.close();  
            // 读取响应  
            int length = (int) connection.getContentLength();// 获取长度  
            InputStream is = connection.getInputStream();  
            if (length != -1) {  
                byte[] data = new byte[length];  
                byte[] temp = new byte[512];  
                int readLen = 0;  
                int destPos = 0;  
                while ((readLen = is.read(temp)) > 0) {  
                    System.arraycopy(temp, 0, data, destPos, readLen);  
                    destPos += readLen;  
                }
                result = new String(data, "UTF-8"); // utf-8编码  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
		return result;
	}
	
	public static String implode(String tag, List<String> str){
		String result = str.get(0);
		for (int i=1;i<str.size();i++) {
			result = result.concat(tag);
			result = result.concat(str.get(i));
		}
		return result;
	}
    
    public static String Sign(String content, String key)
			throws Exception {
		String signStr = "";

		if ("" == key) {
			throw new Exception("财付通签名key不能为空！");
		}
		if ("" == content) {
			throw new Exception("财付通签名内容不能为空");
		}
		signStr = content + "&key=" + key;

		return MD5(signStr).toUpperCase();

	}
    
}
